﻿using System.Reflection;
using System;
using System.Collections.Generic;

namespace Ex03.GarageLogic
{
    /// <summary>
    /// This class will be the Vehicles Constructor
    /// It is a singleton class and you can get a reference
    /// to this class by pointing to the Instance property
    /// </summary>
    public class VehiclesConstructor
    {        
        public enum eVehicleTypeSupported
        {
            [StringValue("Fuel Powered Car")]
            FuelPoweredCar = 1,
            [StringValue("Electric Powered Car")]
            ElectricPoweredCar,
            [StringValue("Fuel Powered Motorcycle")]
            FuelPoweredMotorcycle,
            [StringValue("Electric Powered Motorcycle")]
            ElectricPoweredMotorcycle,
            [StringValue("Van")]
            Van
        }

        private static VehiclesConstructor s_Instance = null;
        private List<string> m_SupportedTypes = null;

        /// <summary>
        /// A privet constructor to prevent the creation of this class
        /// </summary>
        private VehiclesConstructor()
        {
        }

        /// <summary>
        /// A property to get a reference to the static instance of this class 
        /// <remarks>
        /// The first time you address this property it will construct its static
        /// instance member (lazy construction)
        /// </remarks>
        /// </summary>
        public static VehiclesConstructor Instance
        {
            get 
            {
                if (s_Instance == null)
                {            
                    s_Instance = new VehiclesConstructor();
                }

                return s_Instance; 
            }
        }

        /// <summary>
        /// A property that will return a list of the currently supported 
        /// types. 
        /// <remarks>
        /// If this member was not addressed yet it will construct it 
        /// The first time you address this property it will construct a 
        /// supported types member (lazy construction)
        /// </remarks>
        /// </summary>
        public List<string> SupportedTypes
        {
            get
            {
                if (m_SupportedTypes == null)
                {
                    generateSupportedTypes();
                }

                return m_SupportedTypes;
            }
        }

        /// <summary>
        /// This is the main creation method. It will create a new vehicle by type
        /// </summary>
        /// <param name="i_VehicleType">The Vehicle Type</param>
        /// <param name="i_PlateNumber">The Vehicle Plate Number</param>
        /// <returns></returns>
        public Vehicle createVehicleByType(eVehicleTypeSupported i_VehicleType, string i_PlateNumber)
        {
            Vehicle createdVehicle = null;
            switch (i_VehicleType)
            {
                case eVehicleTypeSupported.ElectricPoweredCar:
                    createdVehicle = new ElectricPoweredCar(i_PlateNumber);
                    break;
                case eVehicleTypeSupported.FuelPoweredCar:
                    createdVehicle = new FuelPoweredCar(i_PlateNumber);
                    break;
                case eVehicleTypeSupported.ElectricPoweredMotorcycle:
                    createdVehicle = new ElectricPoweredMotorcycle(i_PlateNumber);
                    break;
                case eVehicleTypeSupported.FuelPoweredMotorcycle:
                    createdVehicle = new FuelPoweredMotorcycle(i_PlateNumber);
                    break;
                case eVehicleTypeSupported.Van:
                    createdVehicle = new Van(i_PlateNumber);
                    break;
            }

            return createdVehicle;
        }

        private void generateSupportedTypes()
        {
            const bool v_Inherit = true;
            Array vehicleTypes = System.Enum.GetValues(typeof(eVehicleTypeSupported));
            Type type;
            FieldInfo fieldInfo;
            StringValue[] attrArray;

            m_SupportedTypes = new List<string>();

            foreach (eVehicleTypeSupported vehicleType in vehicleTypes)
            {
                type = vehicleType.GetType();
                fieldInfo = type.GetField(vehicleType.ToString());
                attrArray = fieldInfo.GetCustomAttributes(typeof(StringValue), !v_Inherit) as StringValue[];

                foreach (StringValue attr in attrArray)
                {
                    m_SupportedTypes.Add(attr.Value);
                }
            }
        }
    }
}
